
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SampleCode.h"
#include "SkDumpCanvas.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "Sk64.h"
#include "SkGradientShader.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkPath.h"
#include "SkPicture.h"
#include "SkRandom.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkTime.h"
#include "SkTypeface.h"
#include "SkXfermode.h"

#include "SkStream.h"
#include "SkXMLParser.h"

///////////////////////////////////////////////////////////////////////////////

#include "SkImageRef_GlobalPool.h"

static SkBitmap load_bitmap()
    {
    SkStream* stream = new SkFILEStream("/skimages/sesame_street_ensemble-hp.jpg");
    SkAutoUnref aur(stream);

    SkBitmap bm;
    if (SkImageDecoder::DecodeStream(stream, &bm, SkBitmap::kNo_Config,
                                     SkImageDecoder::kDecodeBounds_Mode))
        {
        SkPixelRef* pr = new SkImageRef_GlobalPool(stream, bm.config(), 1);
        bm.setPixelRef(pr)->unref();
        }
    return bm;
    }

static void drawCircle(SkCanvas* canvas, int r, SkColor color)
    {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setColor(color);

    canvas->drawCircle(SkIntToScalar(r), SkIntToScalar(r), SkIntToScalar(r),
                       paint);
    }

class PictureView : public SampleView
    {
        SkBitmap fBitmap;
    public:
        PictureView()
            {
            SkImageRef_GlobalPool::SetRAMBudget(16 * 1024);

            fBitmap = load_bitmap();

            fPicture = new SkPicture;
            SkCanvas* canvas = fPicture->beginRecording(100, 100);
            SkPaint paint;
            paint.setAntiAlias(true);

            canvas->drawBitmap(fBitmap, 0, 0, NULL);

            drawCircle(canvas, 50, SK_ColorBLACK);
            fSubPicture = new SkPicture;
            canvas->drawPicture(*fSubPicture);
            canvas->translate(SkIntToScalar(50), 0);
            canvas->drawPicture(*fSubPicture);
            canvas->translate(0, SkIntToScalar(50));
            canvas->drawPicture(*fSubPicture);
            canvas->translate(SkIntToScalar(-50), 0);
            canvas->drawPicture(*fSubPicture);
            // fPicture now has (4) references to us. We can release ours, and just
            // unref fPicture in our destructor, and it will in turn take care of
            // the other references to fSubPicture
            fSubPicture->unref();
            }

        virtual ~PictureView()
            {
            fPicture->unref();
            }

    protected:
        // overrides from SkEventSink
        virtual bool onQuery(SkEvent* evt)
            {
            if (SampleCode::TitleQ(*evt))
                {
                SampleCode::TitleR(evt, "Picture");
                return true;
                }
            return this->INHERITED::onQuery(evt);
            }

        void drawSomething(SkCanvas* canvas)
            {
            SkPaint paint;

            canvas->save();
            canvas->scale(0.5f, 0.5f);
            canvas->drawBitmap(fBitmap, 0, 0, NULL);
            canvas->restore();

            const char beforeStr[] = "before circle";
            const char afterStr[] = "after circle";

            paint.setAntiAlias(true);

            paint.setColor(SK_ColorRED);
            canvas->drawData(beforeStr, sizeof(beforeStr));
            canvas->drawCircle(SkIntToScalar(50), SkIntToScalar(50),
                               SkIntToScalar(40), paint);
            canvas->drawData(afterStr, sizeof(afterStr));
            paint.setColor(SK_ColorBLACK);
            paint.setTextSize(SkIntToScalar(40));
            canvas->drawText("Picture", 7, SkIntToScalar(50), SkIntToScalar(62),
                             paint);

            }

        virtual void onDrawContent(SkCanvas* canvas)
            {
            drawSomething(canvas);

            SkPicture* pict = new SkPicture;
            SkAutoUnref aur(pict);

            drawSomething(pict->beginRecording(100, 100));
            pict->endRecording();

            canvas->save();
            canvas->translate(SkIntToScalar(300), SkIntToScalar(50));
            canvas->scale(-SK_Scalar1, -SK_Scalar1);
            canvas->translate(-SkIntToScalar(100), -SkIntToScalar(50));
            canvas->drawPicture(*pict);
            canvas->restore();

            canvas->save();
            canvas->translate(SkIntToScalar(200), SkIntToScalar(150));
            canvas->scale(SK_Scalar1, -SK_Scalar1);
            canvas->translate(0, -SkIntToScalar(50));
            canvas->drawPicture(*pict);
            canvas->restore();

            canvas->save();
            canvas->translate(SkIntToScalar(100), SkIntToScalar(100));
            canvas->scale(-SK_Scalar1, SK_Scalar1);
            canvas->translate(-SkIntToScalar(100), 0);
            canvas->drawPicture(*pict);
            canvas->restore();

            if (false)
                {
                SkDebugfDumper dumper;
                SkDumpCanvas dumpCanvas(&dumper);
                dumpCanvas.drawPicture(*pict);
                }

            // test that we can re-record a subpicture, and see the results

            SkRandom rand(SampleCode::GetAnimTime());
            canvas->translate(SkIntToScalar(10), SkIntToScalar(250));
            drawCircle(fSubPicture->beginRecording(50, 50), 25,
                       rand.nextU() | 0xFF000000);
            canvas->drawPicture(*fPicture);
            delayInval(500);
            }

    private:
#define INVAL_ALL_TYPE  "inval-all"

        void delayInval(SkMSec delay)
            {
            (new SkEvent(INVAL_ALL_TYPE, this->getSinkID()))->postDelay(delay);
            }

        virtual bool onEvent(const SkEvent& evt)
            {
            if (evt.isType(INVAL_ALL_TYPE))
                {
                this->inval(NULL);
                return true;
                }
            return this->INHERITED::onEvent(evt);
            }

        SkPicture*  fPicture;
        SkPicture*  fSubPicture;

        typedef SampleView INHERITED;
    };

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory()
    {
    return new PictureView;
    }
static SkViewRegister reg(MyFactory);

